﻿namespace DimensionsHelper.Common.Contracts.Metadata;

/// <summary>
///     此接口表示元数据分类字段 或
///     迭代类型是<see cref="IteratorTypes.Categorical" />字段中定义的列表 或
///     使用 codes({}) 定义分类列表中分类元素。
/// </summary>
public interface IElement : IMetadataLabeledObject
{
    /// <summary>
    ///     当前元数据分类元素引用的元素定义列表。
    /// </summary>
    IElementList? Reference { get; }

    /// <summary>
    ///     引用分类列表时使用的引用名称。
    /// </summary>
    string? ReferenceName { get; set; }
        
        
    /// <summary>
    ///     获取或设置当前的元素类型。
    /// </summary>
    ElementType ElementType { get; }

    /// <summary>
    ///     获取或设置当前对象的特殊Categorical类型。
    /// </summary>
    CategoryFlags Flag { get; set; }

    /// <summary>
    ///     指示当前分类元素是否是系统元素。
    /// </summary>
    bool IsSystem { get; }

    /// <summary>
    ///     获取或设置当前分类元素使用的 expression() 表达式。在输出文本时，空白值分两种情况处理：属性值为null时，不输出表达式；值为""时，输出 expression("")。
    /// </summary>
    string? Expression { get; set; }
        
    /// <summary>
    ///     获取或设置当前分类元素使用的 factor() 表达式。如果此值为null，在输出时将忽略。
    /// </summary>
    object? Factor { get; set; }
        
    /// <summary>
    ///     获取或配置当前分类是否是 OTHER 后缀定义并且使用了本地定义的变量。
    /// </summary>
    bool IsOtherLocal { get; }

    /// <summary>
    ///     获取或设置在不使用本地其他变量时，引用的全局变量ID。
    /// </summary>
    string? OtherVariableId { get; set; }
        
    /// <summary>
    ///     获取当前元素的“其他”变量。
    /// </summary>
    IVariable? OtherVariable { get; }

    /// <summary>
    ///     本地定义的其他变量集合。
    /// </summary>
    IVariables LocalOtherVariables { get; }

    /// <summary>
    ///     提示当前分类元素是否带有 multiplier 后缀并且使用本地的定义的变量。
    /// </summary>
    bool IsMultiplierLocal { get; }

    /// <summary>
    ///     获取或设置在不使用本地乘数变量时，引用的全局变量ID。
    /// </summary>
    string? MultiplierVariableId { get; set; }

        
    /// <summary>
    ///     获取当前元素的乘数变量。
    /// </summary>
    IVariable? MultiplierVariable { get; }

    /// <summary>
    ///     本地定义的乘数变量。
    /// </summary>
    IVariables LocalMultiplierVariables { get; }

    /// <summary>
    ///     当前分类元素是否引用了其他列表。
    /// </summary>
    bool IsCategoriesReference { get; }

    /// <summary>
    ///     分类元素引用的元素列表UUID。
    /// </summary>
    string? CategoriesReference { get; }
            

    /// <summary>
    ///     分类元素引用的列表对象。
    /// </summary>
    IElementList? Categories { get; }

    /// <summary>
    ///     当前列表是否可用于筛选。
    /// </summary>
    bool CanFilter { get; }

    /// <summary>
    ///     指示当前分类的值是否是通过计算派生得到的。
    /// </summary>
    bool IsDerived { get; set; }

    /// <summary>
    ///     数据源属性。
    /// </summary>
    IProperties? DataSourceProperties { get; }

    /// <summary>
    ///     获取或设置元素是否固定位置。
    /// </summary>
    bool Fixed { get; }

    /// <summary>
    ///     获取或设置当前元素不保存数据。
    /// </summary>
    bool HasNoData { get; set; }

    /// <summary>
    ///     获取或设置当前元素对应的按键名。
    /// </summary>
    string? KeyCode { get; set; }

    /// <summary>
    ///     获取或设置当前分类元素的排他性。
    /// </summary>
    bool Exclusive { get; }

    /// <summary>
    ///     当前分类元素是否内联。当此属性是true并且引用了其他列表时，不带有sublist关键字，否则，带有sublist关键字。
    /// </summary>
    bool Inline { get; set; }

    /// <summary>
    ///     是否使用全局命名空间。如果此值是false，使用全局命名空间，否则，使用本地命名空间
    /// </summary>
    bool Namespace { get; set; }

    /// <summary>
    ///     获取或设置数据源<see cref="IDataSource" />中定义的本地值。
    /// </summary>
    object? NativeValue { get; set; }
        
    int Nv { get; set; }

    /// <summary>
    ///     分类元素对应的数据库存储值。
    /// </summary>
    int Value { get; }

    /// <summary>
    ///     分类列表中的子列表。
    /// </summary>
    IElements Elements { get; }
}


/// <summary>
///     IElement 对象集合，xml中使用 categories tag定义
/// </summary>
public interface IElements : IMetadataLabeledCollection<IElement>
{
    /// <summary>
    ///     是否使用全局命名空间。如果此值是false，使用全局命名空间，否则，使用本地命名空间
    /// </summary>
    bool Namespace { get; set; }

    /// <summary>
    ///     获取或设置列表是否固定顺序。
    /// </summary>
    bool Fixed { get; set; }

    /// <summary>
    ///     获取或设置列表是否内联。
    /// </summary>
    bool Inline { get; set; }

    /// <summary>
    ///     获取列表是否是数据库分类列表。
    /// </summary>
    bool IsDbElements { get; }

    /// <summary>
    ///     获取或设置当前分类集合引用的分类列表。
    /// </summary>
    string? ReferenceId { get; set; }

    /// <summary>
    ///     当前列表引用的列表。
    /// </summary>
    IElementList? Reference { get; }

    /// <summary>
    ///     获取此列表是否引用了其他列表。
    /// </summary>
    bool IsReference { get; }

    /// <summary>
    ///     如果直接在列表上引用了其他列表，此属性为引用名。
    /// </summary>
    string? ReferenceName { get; set; }
            

    /// <summary>
    ///     获取此列表是否是系统分类列表。
    /// </summary>
    bool IsSystem { get; }

    /// <summary>
    ///     获取或设置此列表是否是派生出来的。当<see cref="Owner" />的类型是<see cref="ICompound" />时，此列表应当从
    ///     loop层变量派生，此值是true。
    /// </summary>
    bool IsDerived { get; set; }

    /// <summary>
    ///     获取当前列表所属字段，如果此列表是通过define关键字定义的列表或者<see cref="IMetadataObject.Parent" />是<see cref="IElement" />，此属性是null。
    /// </summary>
    IField? Owner { get; }

    /// <summary>
    ///     获取此列表的排序方式。
    /// </summary>
    OrderTypes Order { get; set; }

    /// <summary>
    ///     获取此列表的数据库筛选条件。
    /// </summary>
    string? DbFilter { get; set; }
            

    /// <summary>
    ///     向集合中添加一个新的分类元素并返回。
    /// </summary>
    /// <param name="name">元素名</param>
    IElement AddNew(string name);

    /// <summary>
    ///     向集合中添加一个新的引用其他分类列表的分类元素。
    /// </summary>
    /// <param name="name">分类名</param>
    /// <param name="referenceId">引用的列表UUID</param>
    /// <param name="referenceName">引用命名，默认是null</param>
    /// <returns></returns>
    IElement AddNew(string name, string referenceId, string? referenceName = null);

    /// <summary>
    ///     在集合中查找指定名称的分类元素，不区分大小写。
    /// </summary>
    /// <param name="name">给定分类名称</param>
    /// <returns>查找到的元素定义，未定义时返回<see langword="null" /></returns>
    IElement? Find(string name);
}


/// <summary>
///     类型是 <see cref="ElementType.Category" /> 的 IElement 集合。
/// </summary>
public interface ICategories : IMetadataLabeledCollection<IElement>
{
}


/// <summary>
///     分类元素定义的实例引用。
/// </summary>
public interface IElementInstance : IMetadataObject
{
    /// <summary>
    ///     分类元素全名
    /// </summary>
    string FullName { get; set; }
}


/// <summary>
///     分类元素定义的实例引用集合。
/// </summary>
public interface IElementInstances : IMetadataObject, IMetadataObjectCollection
{
}